//
//  PMSegmentShape.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 10/29/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

/**
 * A subclass of PMShape for representing line segment collision shapes. Note that
 * at this time, PMSegmentShapes cannot collide with other PMSegmentShapes. They
 * are intended for use as a static shape.
 */


#import "PMSegmentShape.h"
#import "PMBody.h"


#pragma mark Private Interface
@interface PMSegmentShape (Private)
- (void)updateNormal;
@end
#pragma mark -


@implementation PMSegmentShape


#pragma mark -
#pragma mark Init

/**
 * Returns a PMSegmentShape object initialized to correspond to a given PMBody 
 * object, with given start and end points relative to the body's center of gravity 
 * and width of 0.0.
 */
- (id)initWithBody:(PMBody *)aBody start:(PMVect)start end:(PMVect)end {
	return [self initWithBody:aBody start:start end:end width:0.0];
}

/**
 * Returns a PMSegmentShape object initialized to correspond to a given PMBody
 * object, with given start and end points relative to the body's center of gravity 
 * and given width.
 */
- (id)initWithBody:(PMBody *)aBody start:(PMVect)start end:(PMVect)end width:(PMFloat)width {
	if (![super init])
		return nil;
	
	// allocate and initialize cpShape
	shape = cpSegmentShapeNew(aBody.cpBody, start, end, width/2.0);
	self.body = aBody;
	
	return self;
}


#pragma mark -
#pragma mark Getters

/**
 * Returns the receiver's starting point.
 */
- (PMVect)start {
	return (PMVect) ((cpSegmentShape *) shape)->a;
}

/**
 * Returns the receiver's end point.
 */
- (PMVect)end {
	return (PMVect) ((cpSegmentShape *) shape)->b;
}

/**
 * Returns the receiver's normal vector (Using the right-hand rule for direction).
 */
- (PMVect)normal {
	return (PMVect) ((cpSegmentShape *) shape)->n;
}

/**
 * Returns the receivers width.
 */
- (PMFloat)width {
	return ((cpSegmentShape *) shape)->r / 2.0;
}


#pragma mark -
#pragma mark Setters

/**
 * Sets the receiver's start point to a given position. Use of this method is not 
 * recommended, as it could result in anomalous behavior.
 */
- (void)setStart:(PMVect)start {
	((cpSegmentShape *) shape)->a = start;
	[self updateNormal];
}

/**
 * Sets the receiver's end point to a given position. Use of this method is not 
 * recommended, as it could result in anomalous behavior.
 */
- (void)setEnd:(PMVect)end {
	((cpSegmentShape *) shape)->b = end;
	[self updateNormal];
}

/**
 * Sets the receiver's width to a given value. Use of this method is not recommended,
 * as it could result in anomalous behavior.
 */
- (void)setWidth:(PMFloat)width {
	((cpSegmentShape *) shape)->r = width / 2.0;
}


#pragma mark -
#pragma mark Private Methods

- (void)updateNormal {
	cpVect a = ((cpSegmentShape *) shape)->a;
	cpVect b = ((cpSegmentShape *) shape)->b;
	((cpSegmentShape *) shape)->n = cpvperp(cpvnormalize(cpvsub(b, a)));
}

@end
